home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / mpeg_play-2.1 / fs2.c < prev    next >
C/C++ Source or Header  |  1995-05-09  |  9KB  |  394 lines

  1. /*
  2.  * fs2.c --
  3.  *
  4.  *      Procedures dealing with Floyd-Steinberg dithering with 2 error
  5.  *      values propagated.
  6.  *
  7.  */
  8.  
  9. /*
  10.  * Copyright (c) 1995 The Regents of the University of California.
  11.  * All rights reserved.
  12.  * 
  13.  * Permission to use, copy, modify, and distribute this software and its
  14.  * documentation for any purpose, without fee, and without written agreement is
  15.  * hereby granted, provided that the above copyright notice and the following
  16.  * two paragraphs appear in all copies of this software.
  17.  * 
  18.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  19.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  20.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  21.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  22.  * 
  23.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  24.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  25.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  26.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  27.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  28.  */
  29.  
  30. #include "video.h"
  31. #include "dither.h"
  32. #include "fs2.h"
  33. #include "proto.h"
  34. #include <malloc.h>
  35.  
  36. /* Structures for precomputed error propogation values. */
  37.  
  38. static FS2DithVal lum_index[256];
  39. static FS2DithVal cr_index[256];
  40. static FS2DithVal cb_index[256];
  41.  
  42.  
  43.  
  44. /*
  45.  *--------------------------------------------------------------
  46.  *
  47.  * InitFS2Dither --
  48.  *
  49.  *    Initializes structures for precomputed 2 error f-s dithering.
  50.  *      The value field of the structure contains the pixel component 
  51.  *      of the particular channel in question. Thus the addition of
  52.  *      the value field of a structure in the luminance index, a 
  53.  *      structure in the Cr index, and a structure in the Cb index will
  54.  *      yeild a color number. This color number can then be transformed
  55.  *      into a pixel value to be displayed. Each channel can then be
  56.  *      processed (i.e. dithered) separately, with the results being
  57.  *      added up and remapped to yield a final pixel value.
  58.  *
  59.  * Results:
  60.  *    None.
  61.  *
  62.  * Side effects:
  63.  *      None.
  64.  *
  65.  *--------------------------------------------------------------
  66.  */
  67.  
  68. void InitFS2Dither()
  69. {
  70.   int i;
  71.  
  72.   /* For each possible pixel value, precompute propogated error and
  73.      store in array.
  74.   */
  75.   
  76.   for (i=0; i<256; i++) {
  77.     lum_index[i].value = (i * LUM_RANGE) / 256;
  78.  
  79.     lum_index[i].e1 = (i-lum_values[lum_index[i].value]) / 2;
  80.     lum_index[i].e3 = (i - lum_values[lum_index[i].value]) - lum_index[i].e1;
  81.  
  82.     lum_index[i].value *= LUM_BASE;
  83.  
  84.     cr_index[i].value = (i * CR_RANGE) / 256; 
  85.  
  86.     cr_index[i].e1 = (i - cr_values[cr_index[i].value]) / 2;
  87.     cr_index[i].e3 = (i - cr_values[cr_index[i].value]) - cr_index[i].e1 ;
  88.  
  89.     cr_index[i].value *= CR_BASE;
  90.  
  91.     cb_index[i].value = (i * CB_RANGE) / 256; 
  92.  
  93.     cb_index[i].e1 = (i - cb_values[cb_index[i].value]) / 2;
  94.     cb_index[i].e3 = (i - cb_values[cb_index[i].value]) - cb_index[i].e1;
  95.  
  96.     cb_index[i].value *= CB_BASE;
  97.  
  98.   }
  99.  
  100. }
  101.  
  102.  
  103. /*
  104.  *--------------------------------------------------------------
  105.  *
  106.  * DitherImage --
  107.  *
  108.  *    Converts lum, cr, cb image planes into fixed colormap
  109.  *      space.
  110.  *
  111.  * Results:
  112.  *    the display plane is replaced by 8-bit colormap space
  113.  *      image.
  114.  *
  115.  * Side effects:
  116.  *      Hopefully, none.
  117.  *
  118.  *--------------------------------------------------------------
  119.  */
  120.  
  121. void FS2DitherImage(lum, cr, cb, disp, rows, cols)
  122.      unsigned char *lum, *cr, *cb, *disp;
  123.      int rows, cols;
  124. {
  125.   static char *cur_row_error, *next_row_error;
  126.   static int first = 1;
  127.   char  *cur_row_err_mark, *next_row_err_mark;
  128.   char *temp;
  129.   int i, j, pixsum, c_cols;
  130.   unsigned char *cur_row, *channel, *dest_row;
  131.   FS2DithVal *chan_index;
  132.  
  133.   /* Allocate error arrays. */
  134.  
  135.   if (first) {
  136.     cur_row_error = (char *) malloc((unsigned int) cols+2);
  137.     next_row_error = (char *) malloc((unsigned int) cols+2);
  138.     first = 0;
  139.   }
  140.  
  141.   /* Initialize error arrays. */
  142.  
  143.   memset(cur_row_error, 0, cols+2);
  144.   memset(next_row_error, 0, cols+2);
  145.  
  146.   /* Use luminance values first. */
  147.  
  148.   /* For each two rows, do... */
  149.  
  150.   for(i=0; i<rows; i+=2) {
  151.  
  152.     /* Establish pointer to current source and destination rows. */
  153.     cur_row = lum + (i*cols);
  154.     dest_row = disp + (i*cols);
  155.  
  156.     /* Establish pointers to error arrays. */
  157.     cur_row_err_mark = cur_row_error + 1;
  158.     next_row_err_mark = next_row_error + 1;
  159.  
  160.     
  161.     /* For each column within first row do... */
  162.  
  163.     for (j=0; j<cols; j++) {
  164.  
  165.       /* Calculate pixel value with error. */
  166.  
  167.       pixsum = *cur_row + *cur_row_err_mark;
  168.  
  169.       /* Bounds check. */
  170.       if (pixsum < 0) pixsum = 0;
  171.       else if (pixsum > 255) pixsum = 255;
  172.  
  173.       /* Establish dest value, propogate errors. */
  174.  
  175.       *dest_row = lum_index[pixsum].value;
  176.       *(cur_row_err_mark+1) += lum_index[pixsum].e1; 
  177.       *next_row_err_mark += lum_index[pixsum].e3; 
  178.  
  179.       /* Advance pointers. */
  180.  
  181.       cur_row++;
  182.       dest_row++;
  183.       cur_row_err_mark++;
  184.       next_row_err_mark++;
  185.     }
  186.  
  187.     /* Switch error arrays, so next row errors are now current row errors, and
  188.        vice versa. 
  189.     */
  190.  
  191.     temp = cur_row_error;
  192.     cur_row_error = next_row_error;
  193.     next_row_error = temp;
  194.  
  195.     /* Reset next row errors. */
  196.  
  197.     memset(next_row_error, 0, cols+2); 
  198.  
  199.     /* Establish pointers for second row. This one will be processed right to
  200.        left to establish serpantine motion.
  201.     */
  202.  
  203.     cur_row += cols-1;
  204.     dest_row += cols-1;
  205.     cur_row_err_mark = cur_row_error + cols;
  206.     next_row_err_mark = next_row_error + cols;
  207.  
  208.     /* Process each column... */
  209.  
  210.     for (j=0; j<cols; j++) {
  211.  
  212.       pixsum = *cur_row + *cur_row_err_mark;
  213.       if (pixsum < 0) pixsum = 0;
  214.       else if (pixsum > 255) pixsum = 255;
  215.       
  216.       *dest_row = lum_index[pixsum].value;
  217.       *(cur_row_err_mark-1) += lum_index[pixsum].e1; 
  218.       *next_row_err_mark += lum_index[pixsum].e3; 
  219.       
  220.       cur_row--;
  221.       dest_row--;
  222.       cur_row_err_mark--;
  223.       next_row_err_mark--;
  224.     }
  225.  
  226.     /* Switch error arrays. */
  227.  
  228.     temp = cur_row_error;
  229.     cur_row_error = next_row_error;
  230.     next_row_error = temp;
  231.  
  232.     /* Reset next row errors. */
  233.  
  234.     memset(next_row_error, 0, cols+2); 
  235.   }
  236.  
  237.   /* Reset error arrays. */
  238.  
  239.   memset(cur_row_error, 0, cols+2); 
  240.   
  241.   /* Establish column length divided by two. */
  242.  
  243.   c_cols = cols >> 1;
  244.  
  245.   /* Set channel to Cr. Use Cr index. */
  246.  
  247.   channel = cr;
  248.   chan_index = cr_index;
  249.   
  250.  repeat:
  251.  
  252.   /* Process each row of chrominance data... */
  253.  
  254.   for (i=0; i < rows; i+=2) {
  255.  
  256.     /* Establish pointers. */
  257.  
  258.     cur_row = channel + ((i>>1)*c_cols);
  259.     dest_row = disp + (i*cols);
  260.  
  261.     cur_row_err_mark = cur_row_error+1;
  262.     next_row_err_mark = next_row_error+1;
  263.  
  264.     /* For each column in row... */
  265.  
  266.     for (j=0; j<cols; j++) {
  267.       int p_val;
  268.  
  269.       /* Get pixel value as twos bit complement. */
  270.  
  271.       p_val = *cur_row;
  272.  
  273.       /* Add error term. */
  274.  
  275.       pixsum = *cur_row_err_mark + p_val;
  276.  
  277.       /* Bounds check. */
  278.  
  279.       if (pixsum < 0) pixsum = 0;
  280.       else if (pixsum > 255) pixsum = 255;
  281.  
  282.       /* Increment dest value. */
  283.  
  284.       *dest_row += chan_index[pixsum].value;
  285.  
  286.       /* Propogate error values. */
  287.  
  288.       *(cur_row_err_mark+1) += chan_index[pixsum].e1; 
  289.       *next_row_err_mark += chan_index[pixsum].e3; 
  290.  
  291.  
  292.       /* If count is odd, advance source pointer (Cr and Cb channels are 2:1 
  293.      subsampled.
  294.       */
  295.  
  296.       if (j&1) cur_row++;
  297.  
  298.       /* Advance destination and error pointers. */
  299.  
  300.       dest_row++;
  301.       cur_row_err_mark++;
  302.       next_row_err_mark++;
  303.     }
  304.  
  305.     /* Switch error arrays. */
  306.  
  307.     temp = cur_row_error;
  308.     cur_row_error = next_row_error;
  309.     next_row_error = temp;
  310.  
  311.     /* Reset next row errors. */
  312.  
  313.     memset(next_row_error, 0, cols+2);
  314.  
  315.     /* Re-establish pointers. */
  316.  
  317.     cur_row += c_cols-1;
  318.     dest_row += cols-1;
  319.     cur_row_err_mark = cur_row_error+cols;
  320.     next_row_err_mark = next_row_error+cols;
  321.  
  322.     /* Process second row right to left. */
  323.  
  324.     for (j=0; j<cols; j++) {
  325.       int p_val;
  326.  
  327.       /* Get source value as twos bit complement. */
  328.  
  329.       p_val = *cur_row;
  330.  
  331.       /* Add error. */
  332.  
  333.       pixsum = *cur_row_err_mark + p_val;
  334.  
  335.       /* Bounds check. */
  336.  
  337.       if (pixsum < 0) pixsum = 0;
  338.       else if (pixsum > 255) pixsum = 255;
  339.  
  340.       /* Increment dest value. */
  341.  
  342.       *dest_row += chan_index[pixsum].value;
  343.  
  344.       /* Propogate errors. */
  345.  
  346.       *(cur_row_err_mark-1) += chan_index[pixsum].e1; 
  347.       *next_row_err_mark += chan_index[pixsum].e3; 
  348.  
  349.       /* If column counters is odd, decrement source pointer. */
  350.  
  351.       if (j&1) cur_row--;
  352.  
  353.       /* Decrement dest and error pointers. */
  354.  
  355.       dest_row--;
  356.       cur_row_err_mark--;
  357.       next_row_err_mark--;
  358.     }
  359.  
  360.     /* Switch error arrays. */
  361.  
  362.     temp = cur_row_error;
  363.     cur_row_error = next_row_error;
  364.     next_row_error = temp;
  365.  
  366.     /* Reinitialize next row errors. */
  367.  
  368.     memset(next_row_error, 0, cols+2);
  369.   }
  370.  
  371.   /* If Cr channel completed, set channel to Cb and Cb index and repeat. */
  372.  
  373.   if (channel == cr) {
  374.     channel = cb;
  375.     chan_index = cb_index;
  376.     memset(cur_row_error, 0, cols+2);
  377.  
  378.     goto repeat;
  379.   }
  380.  
  381.   /* Establish pointer to start of display frame. */
  382.  
  383.   dest_row = disp;
  384.  
  385.   /* Transform all display values to pixel values. */
  386.  
  387.   for (i=0; i<rows; i++) {
  388.     for (j=0; j<cols; j++) {
  389.       *dest_row =  pixel[*dest_row];
  390.       dest_row++;
  391.     }
  392.   }
  393. }
  394.